package engineer.view;

import engineer.reverse.Revert;
import engineer.Engineer;
import engineer.view.database.connect.ConnectController;
import engineer.view.database.schema.SchemaController;
import engineer.view.entity_model.EntityModelController;
import engineer.view.help.about.About;
import engineer.view.laravel.LaravelController;
import entity_model.EntityModel;
import fx.FX;
import fx.SceneBuilder;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import laravel.Laravel;
import utils.Utils;
import utils.titles.Title;
import mysql.Schema;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;

import static engineer.reverse.schema.RevertSchema.ExtensionFilters.EEM;

/**
 * Created by thormentor on 27-04-2014.
 */
public class EngineerApplication extends Application{
    @FXML
    private MenuItem fileCloseMenuItem;

    @FXML
    private MenuItem fileSaveAsMenuItem;

    @FXML
    private MenuItem fileSaveMenuItem;

    @FXML
    private TabPane tabPane;

    private About about;
    private Stage stage;
    private ConnectController connectController;
    private static int nextId = 1;

    @Override
    public void start(Stage stage) throws Exception {
        this.stage = stage;
        stage.setMaximized(true);
        new SceneBuilder(this, stage)
            .build();
    }

    @FXML
    private void initialize(){
    }

    public static void main(String... args) {
        launch(args);
    }

    public void fileNew(ActionEvent actionEvent) {
        open(new EntityModel(Title.fromCapitalized("Entity model " + nextId++)));
    }

    public void fileLoad(ActionEvent actionEvent) {
        // configureFileChooser(fileChooser); FIXME
        final FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("Open entity model");
        fileChooser.setInitialDirectory(Engineer.FOLDER.getFile());
        fileChooser.getExtensionFilters().add(EEM);
        File file = fileChooser.showOpenDialog(stage);
        if (file != null) {
            try {
                ((EntityModelController)open(Utils.getGson().fromJson(new FileReader(file), EntityModel.class)).getContent()).setFile(file);
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public void fileSave(ActionEvent actionEvent) {
        ((EntityModelController) tabPane.getSelectionModel().getSelectedItem().getContent()).save();
    }

    public void fileSaveAs(ActionEvent actionEvent) {
        ((EntityModelController) tabPane.getSelectionModel().getSelectedItem().getContent()).saveAs();
    }

    public void fileExit(ActionEvent actionEvent) {
        System.exit(1);
    }

    public void schemaConnect(ActionEvent actionEvent) {
        if (connectController == null)
            connectController = new ConnectController();

        connectController.connectionProperty.addListener((a, b, connection) -> {
            Schema schema = new Schema(connection);
            SchemaController schemaController = new SchemaController();
            schemaController.setSchema(schema);
            Tab tab = new Tab(schemaController.toString());
            tab.setContent(schemaController);
            tabPane.getTabs().add(tab);
            tab.setOnSelectionChanged(event -> {
                if (tab.isSelected()) {
                    fileSaveMenuItem.setDisable(true);
                    fileSaveAsMenuItem.setDisable(true);
                    fileCloseMenuItem.setDisable(true);
                }
            });
        });

        FX.popup(connectController);
    }

    public void helpAbout(ActionEvent actionEvent) {
        if (about == null)
            about = new About();

        FX.popup(about);
    }

    public void fileClose(ActionEvent actionEvent) {
        tabPane.getTabs().remove(tabPane.getSelectionModel().getSelectedItem());
    }

    public void databaseReverseEngineer(ActionEvent actionEvent) {
        final Node content = tabPane.getSelectionModel().getSelectedItem().getContent();

        if (content instanceof SchemaController)
            ((SchemaController) content).revert((observable, oldValue, newValue) -> open(((Revert) observable).getEntityModel()));
    }

    private EntityModelTab open(EntityModel entityModel) {
        EntityModelTab tab = new EntityModelTab(entityModel);

        tabPane.getTabs().add(tab);
        tabPane.getSelectionModel().select(tab);

        return tab;
    }

    private LaravelTab open(Laravel laravel) {
        LaravelTab tab = new LaravelTab(laravel);

        tabPane.getTabs().add(tab);
        tabPane.getSelectionModel().select(tab);

        return tab;
    }

    private class LaravelTab extends Tab {
        private LaravelController laravelController = new LaravelController();

        public LaravelTab(Laravel laravel){
            super(laravel.toString());

            laravelController.setLaravel(laravel);
            setContent(laravelController);
        }
    }

    private class EntityModelTab extends Tab {
        private EntityModelController entityModelController = new EntityModelController();

        public EntityModelTab(EntityModel entityModel) {
            super(entityModel.toString());

            entityModelController.setEntityModel(entityModel);
            setContent(entityModelController);

            entityModelController.laravelProperty.addListener((observable, oldValue, newValue) -> open(newValue));

            setOnSelectionChanged(event -> {
                if (isSelected()) {
                    fileSaveMenuItem.setDisable(false);
                    fileSaveAsMenuItem.setDisable(false);
                    fileCloseMenuItem.setDisable(false);
                }
            });
        }
    }
}
